package cn.imokay.juc.jmm;

import java.util.concurrent.TimeUnit;

public class VolatileNoAtomicDemo {
    public static void main(String[] args) {
        MyNumber myNumber = new MyNumber();
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                for (int i1 = 0; i1 < 1000; i1++) {
                    myNumber.addPlusPlus();
                }
            }).start();
        }

        try { TimeUnit.SECONDS.sleep(5); } catch (Exception e) { e.printStackTrace();}
        System.out.println(myNumber.number);//每次打印结果不一致，不加锁的话，操作没有原子性
    }
}

class MyNumber{
    volatile int number;
    public synchronized void addPlusPlus(){
        number++;
        /**
         * number++ 实际上包含了3不操作：加载数据，计算数据，
         * 重新赋值，没有加锁时，这三个操作是不具备原子性，
         * 由于volitile修饰，在计算到一半的时候，
         *      其他线程的修改会被当前线程立即知道，回去主内存获取最近值到工作内存，
         *      同时本次的操作就会被作废，浪费了一次循环计算的机会，所以导结果指挥接近10000，大概率达不到10000
         *
         *      原子性要求，一些列操作必须不被干扰的独享资源进行
         *
         * 因此volatile不符合下面两条规则时，仍需加锁：
         *  （1）.运算结果并不依赖变量的当前值，或者能够明确知道只有单一线程修改变量的值
         *  （2）.变量不需要与其他的状态变量共同参与不变约束
         */
    }
}